﻿using System;
using System.Collections.Generic;
using System.Text;
using MYTech.Data;

namespace MYTech.Utils
{
    /// <summary>
    /// 时间帮助类
    /// </summary>
    public class TimeHelper
    {
        #region 时间形式转化
        /// <summary>
        /// 转化为数据库时间类型
        /// </summary>
        /// <param name="Time"></param>
        /// <returns></returns>
        public static string ToDateTime(DateTime Time)
        {
            return string.Format("TIMESTAMP' {0:yyyy-MM-dd HH:mm:ss}'", Time);
        }

        /// <summary>
        /// 转化为数据库时间类型
        /// </summary>
        /// <param name="Time"></param>
        /// <returns></returns>
        public static string ToDateTime(string Time)
        {
            return string.Format("TIMESTAMP' {0}'", Time);
        }

        /// <summary>
        /// 时间范围
        /// </summary>
        /// <param name="fieldname"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        public static string TimeBetween(string fieldname, DateTime startTime, DateTime endTime)
        {
            return string.Format("{0}>={1} and {0}<{2}", fieldname, ToDateTime(startTime), ToDateTime(endTime));
        }

        /// <summary>
        /// 时间范围
        /// </summary>
        /// <param name="fieldname"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <returns></returns>
        public static string TimeBetween(string fieldname, string startTime, string endTime)
        {
            return string.Format("{0}>={1} and {0}<{2}", fieldname, ToDateTime(startTime), ToDateTime(endTime));
        }

        /// <summary>
        /// 将时间字符串转化为时间类型
        /// </summary>
        /// <param name="time">if the time string is 121230,then the time is 2012-12-30,and the Format should be yyMMdd</param>
        /// <param name="format"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(string time, string format)
        {
            try
            {
                return DateTime.ParseExact(time, format, System.Globalization.CultureInfo.CurrentCulture);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region 时间点获取
        /// <summary>
        /// 本月第一天时间
        /// </summary>
        /// <returns></returns>
        public static DateTime FirstDayOfMonth()
        {
            return DateTime.Now.Date.AddDays(1 - DateTime.Now.Date.Day);
        }

        public static DateTime FirstDayOfMonth(DateTime dt)
        {
            return dt.Date.AddDays(1 - dt.Date.Day);
        }

        /// <summary>
        /// 本周第一天时间
        /// </summary>
        /// <returns></returns>
        public static DateTime FirstDayOfWeek()
        {
            return DateTime.Now.Date.AddDays(1 - Convert.ToInt32(DateTime.Now.Date.DayOfWeek.ToString("d")));
        }

        /// <summary>
        /// 获取指定日期所在周的第一天时间
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime FirstDayOfWeek(DateTime dt)
        {
            return dt.Date.AddDays(dt.DayOfWeek == DayOfWeek.Sunday ? -6 : -(int)dt.DayOfWeek + 1);
        }

        /// <summary>
        /// 获取指定日期为一年中的第几周
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static int WeekOfYear(DateTime dt)
        {
            DateTime firstDay = new DateTime(dt.Year, 1, 1);
            int days = dt.DayOfYear + (firstDay.DayOfWeek == DayOfWeek.Sunday ? 5 : (int)firstDay.DayOfWeek - 2);
            return days / 7;
        }

        /// <summary>
        /// 按月、周、天、小时分类获取时间范围内时间点
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="type">0表示月，1表示周，2表示天，3表示小时</param>
        /// <returns></returns>
        public static List<DateTime> GetTimeRangePoints(DateTime start, DateTime end, int type)
        {
            List<DateTime> times = new List<DateTime>();
            switch (type)
            {
                case 0:
                    {
                        int count = (end.Year - start.Year) * 12 + end.Month - start.Month + 1;
                        DateTime startMonth = FirstDayOfMonth(start);
                        for (int index = 0; index < count; index++)
                        {
                            times.Add(startMonth.AddMonths(index));
                        }
                        return times;
                    }
                case 1:
                    {
                        int count = (int)(end - start).TotalDays / 7 + 1;
                        DateTime startWeek = FirstDayOfWeek(start);
                        for (int index = 0; index < count; index++)
                        {
                            times.Add(startWeek.AddDays(index * 7));
                        }
                        return times;
                    }
                case 2:
                    {
                        int count = 1 + (int)(end - start).TotalDays;
                        for (int index = 0; index < count; index++)
                        {
                            times.Add(start.Date.AddDays(index));
                        }
                        return times;
                    }
                case 3:
                default:
                    {
                        int count = 1 + (int)(end - start).TotalHours;
                        for (int index = 0; index < count; index++)
                        {
                            times.Add(start.Date.AddHours(start.Hour).AddHours(index));
                        }
                        return times;
                    }
            }
        }

        /// <summary>
        /// 按月、周、天、小时分类获取下个时间点
        /// </summary>
        /// <param name="time"></param>
        /// <param name="type">0表示月，1表示周，2表示天，3表示小时</param>
        /// <returns></returns>
        public static DateTime GetNextTimePoint(DateTime time, int type)
        {
            switch (type)
            {
                case 0:
                    return time.AddMonths(1);
                case 1:
                    return time.AddDays(7);
                case 2:
                    return time.AddDays(1);
                case 3:
                default:
                    return time.AddHours(1);
            }
        }
        #endregion

        #region 时间段获取

        /// <summary>
        /// 给定结束时间和天数，生成满足条件的多个时间间隔
        /// </summary>
        /// <param name="endTime">结束日期</param>
        /// <param name="daysCount">累积天数</param>
        /// <param name="dayOfWeeks">需过滤掉的星期几</param>
        /// <param name="startSpan">起始时间</param>
        /// <param name="endSpan">结束时间</param>
        /// <returns></returns>
        public static List<TimePeriod> GetIntervalTimes(DateTime endTime, int daysCount, List<DayOfWeek> dayOfWeeks, TimeSpan startSpan, TimeSpan endSpan)
        {
            TimePeriod[] timeList = new TimePeriod[daysCount];
            int num = 0, count = 0;
            while (count < daysCount)
            {
                DateTime _time = endTime.AddDays(-num);
                num++;
                bool isMatch = false;

#if !DEBUG
                if (dayOfWeeks != null && dayOfWeeks.Count > 0)
                {
                    isMatch = dayOfWeeks.Exists((day) =>
                    {
                        if (day == _time.DayOfWeek)
                            return true;
                        else
                            return false;
                    }
                    );
                }
#else
                if (dayOfWeeks != null && dayOfWeeks.Count > 0)
                {
                    foreach (DayOfWeek day in dayOfWeeks)
                    {
                        if (_time.DayOfWeek == day)
                        {
                            isMatch = true;
                            break;
                        }
                    }
                }
#endif
                if (!isMatch)
                    timeList[count++] = new TimePeriod() { EndTime = _time.Date.Add(endSpan), StartTime = _time.Date.Add(startSpan) };
            }
            return ConvertTo.ToList(timeList);
        }

        /// <summary>
        /// 给定结束时间和天数，生成满足条件的多个时间间隔
        /// </summary>
        /// <param name="endTime">结束日期</param>
        /// <param name="daysCount">累积天数</param>
        /// <param name="startSpan">起始时间</param>
        /// <param name="endSpan">结束时间</param>
        /// <returns></returns>
        public static List<TimePeriod> GetIntervalTimes(DateTime endTime, int daysCount, TimeSpan startSpan, TimeSpan endSpan)
        {
            return GetIntervalTimes(endTime, daysCount, null, startSpan, endSpan);
        }

        /// <summary>
        /// 给定结束时间和天数，生成满足条件的多个时间间隔,起始时间默认0点，isAllDay为false时，结束时间为当前endTime的时间
        /// </summary>
        /// <param name="endTime">结束日期</param>
        /// <param name="daysCount">累积天数</param>
        /// <param name="dayOfWeeks">需过滤掉的星期几</param>
        /// <param name="isAllDay">是否为全天时间</param>
        /// <returns></returns>
        public static List<TimePeriod> GetIntervalTimes(DateTime endTime, int daysCount, List<DayOfWeek> dayOfWeeks, bool isAllDay)
        {
            if (isAllDay)
                return GetIntervalTimes(endTime, daysCount, dayOfWeeks, new TimeSpan(0), new TimeSpan(1, 0, 0, 0));
            else
                return GetIntervalTimes(endTime, daysCount, dayOfWeeks, new TimeSpan(0), endTime.TimeOfDay);
        }

        /// <summary>
        /// 给定结束时间和天数，生成满足条件的多个时间间隔,起始时间默认0点，结束时间为当日的最后时间
        /// </summary>
        /// <param name="endTime">结束日期</param>
        /// <param name="daysCount">累积天数</param>
        /// <param name="dayOfWeeks">需过滤掉的星期几</param>
        /// <returns></returns>
        public static List<TimePeriod> GetIntervalTimes(DateTime endTime, int daysCount, List<DayOfWeek> dayOfWeeks)
        {
            return GetIntervalTimes(endTime, daysCount, dayOfWeeks, true);
        }

        /// <summary>
        /// 给定结束时间和天数，生成满足条件的多个时间间隔,起始时间默认0点，isAllDay为false时，结束时间为当前endTime的时间
        /// </summary>
        /// <param name="endTime">结束日期</param>
        /// <param name="daysCount">累积天数</param>
        /// <param name="withWeekend">是否包含周末</param>
        /// <returns></returns>
        public static List<TimePeriod> GetIntervalTimes(DateTime endTime, int daysCount, bool withWeekend, bool isAllDay)
        {
            if (withWeekend)
            {
                return GetIntervalTimes(endTime, daysCount, null, isAllDay);
            }
            return GetIntervalTimes(endTime, daysCount, new List<DayOfWeek>() { DayOfWeek.Saturday, DayOfWeek.Sunday }, isAllDay);
        }

        /// <summary>
        /// 给定结束时间和天数，生成满足条件的多个时间间隔；起始时间默认0点，结束时间为当日的最后时间
        /// </summary>
        /// <param name="endTime">结束日期</param>
        /// <param name="daysCount">累积天数</param>
        /// <param name="withWeekend">是否包含周末</param>
        /// <returns></returns>
        public static List<TimePeriod> GetIntervalTimes(DateTime endTime, int daysCount, bool withWeekend)
        {
            return GetIntervalTimes(endTime, daysCount, withWeekend, true);
        }

        /// <summary>
        /// 给定结束时间和天数，生成满足条件的多个时间间隔，包含周末时间；起始时间默认0点，结束时间为当日的最后时间
        /// </summary>
        /// <param name="endTime">结束日期</param>
        /// <param name="daysCount">累积天数</param>
        /// <returns></returns>
        public static List<TimePeriod> GetIntervalTimes(DateTime endTime, int daysCount)
        {
            return GetIntervalTimes(endTime, daysCount, true);
        }

        #endregion
    }
}
